package com.master.lib.ext

import android.app.Activity
import android.graphics.Point
import android.graphics.Rect
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewTreeObserver
import android.view.animation.AnimationUtils
import androidx.annotation.AnimRes
import androidx.annotation.LayoutRes
import androidx.core.view.isGone
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import com.master.lib.utils.KeyboardUtils

val View.activity: Activity?
    get() = context.activity

fun View.setOnOnceClickListener(listener: View.OnClickListener) {
    setOnOnceClickListener { listener.onClick(it) }
}

fun View.setOnOnceClickListener(delay: Int = 500, listener: View.OnClickListener) {
    setOnClickListener {
        val tagKey = Int.MAX_VALUE - 1001
        val tag = it.getTag(tagKey)
        if (tag != null && System.currentTimeMillis() - (tag as Long) < delay) {
            return@setOnClickListener
        }
        listener.onClick(it)
        it.setTag(tagKey, System.currentTimeMillis())
    }
}

fun View.gone() = run { isGone = true }

fun View.visible() = run { isVisible = true }

fun View.invisible() = run { isInvisible = true }

inline fun View.visibleIf(crossinline predicate: () -> Boolean) = apply {
    if (!isVisible && predicate()) isVisible = true
}

fun View.getString(resId: Int): String = resources.getString(resId)

fun View.showKeyboard(flags: Int = 0) = KeyboardUtils.showKeyboard(this, flags)

fun View.hideKeyboard() = KeyboardUtils.hideKeyboard(this)

inline fun <T : View> T.afterMeasured(crossinline predicate: () -> Unit) {
    viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
        override fun onGlobalLayout() {
            if (measuredWidth > 0 && measuredHeight > 0) {
                viewTreeObserver.removeOnGlobalLayoutListener(this)
                predicate.invoke()
            }
        }
    })
}

fun View.setWidth(width: Int, defaultHeight: Int = ViewGroup.LayoutParams.WRAP_CONTENT) {
    var lp = layoutParams
    if (lp == null) {
        lp = ViewGroup.LayoutParams(width, defaultHeight)
    } else {
        lp.width = width
    }
    layoutParams = lp
}

fun View.setHeight(height: Int, defaultWidth: Int = ViewGroup.LayoutParams.WRAP_CONTENT) {
    var lp = layoutParams
    if (lp == null) {
        lp = ViewGroup.LayoutParams(defaultWidth, height)
    } else {
        lp.height = height
    }
    layoutParams = lp
}

fun View.setSize(width: Int, height: Int) {
    var lp = layoutParams
    if (lp == null) {
        lp = ViewGroup.LayoutParams(width, height)
    } else {
        lp.width = width
        lp.height = height
    }
    layoutParams = lp
}

fun View.getLocalVisibleRect(): Rect {
    val rect = Rect()
    getLocalVisibleRect(rect)
    return rect
}

fun View.getGlobalVisibleRect(): Rect {
    val rect = Rect()
    getGlobalVisibleRect(rect)
    return rect
}

fun View.getLocationOnScreen(): Point {
    val location = IntArray(2)
    getLocationOnScreen(location)
    return Point(location[0], location[1])
}

fun View.getLocationInWindow(): Point {
    val location = IntArray(2)
    getLocationInWindow(location)
    return Point(location[0], location[1])
}

fun View.setPaddingLeft(paddingLeft: Int) {
    setPaddingRelative(paddingLeft, paddingTop, paddingRight, paddingBottom)
}

fun View.setPaddingTop(paddingTop: Int) {
    setPaddingRelative(paddingLeft, paddingTop, paddingRight, paddingBottom)
}

fun View.setPaddingRight(paddingRight: Int) {
    setPaddingRelative(paddingLeft, paddingTop, paddingRight, paddingBottom)
}

fun View.setPaddingBottom(paddingBottom: Int) {
    setPaddingRelative(paddingLeft, paddingTop, paddingRight, paddingBottom)
}

fun View.setPaddingHorizontal(padding: Int) {
    setPaddingRelative(padding, paddingTop, padding, paddingBottom)
}

fun View.setPaddingVertical(padding: Int) {
    setPaddingRelative(paddingStart, padding, paddingEnd, padding)
}

fun View.startAnimation(@AnimRes animRes: Int) {
    startAnimation(AnimationUtils.loadAnimation(context, animRes))
}

fun ViewGroup.inflater(
    @LayoutRes layoutId: Int, root: ViewGroup = this, attachToRoot: Boolean = false
): View {
    return LayoutInflater.from(context).inflate(layoutId, root, attachToRoot)
}